package se.su.dsv.theclient;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Iterator;

import theserver.DeviceInfo;
import theserver.DeviceList;
import theserver.VenueActivity;
import theserver.VenueList;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.widget.Toast;

public class SocialService extends Service {
	private ClientDBAdapter dbHelper;
	private int m_value = 0;
	private CheckInThread client;
	private ServerThread server;
	private DeviceList devices;
	private VenueList venuelist;
	private String ipAddress = "localhost";
	private String remoteAddress = "10.0.2.2";
	private String bssid = "3";
	private int localport = 31337;
	private int remoteport = 2000;
	private DeviceInfo myDeviceInfo;

	public boolean ping;
	public boolean listening;

	private String servicestatus = "";
	
	private final long CHECK_IN_INTERVAL = 300000;


	//	private EditText m_inputValue;
	//	private TextView m_textResult;


	private final ISocialService.Stub m_binder = new ISocialService.Stub(){

		@Override
		public int getValue() throws RemoteException {
			return m_value;
		}

		@Override
		public void setValue(int value) throws RemoteException {
			m_value = value;
		}

		@Override
		public int getActivityList(String venue, String[] activities) throws RemoteException {
			ArrayList<String> tmparr = new ArrayList<String>();
			for (Iterator iterator = venuelist.iterator(); iterator.hasNext();) {
				VenueActivity va = (VenueActivity) iterator.next();
				tmparr.add(va.getActivity());
			}
			activities = tmparr.toArray(activities);
			return activities.length;
		}

		@Override
		public int getVenueList(String activity, String[] venues) throws RemoteException {
			ArrayList<String> tmparr = new ArrayList<String>();
			boolean all = activity.equalsIgnoreCase("all");
			for (Iterator iterator = venuelist.iterator(); iterator.hasNext();) {
				VenueActivity va = (VenueActivity) iterator.next();
				if (all) {
					tmparr.add(va.getVenue());
				}
			}
			venues = tmparr.toArray(venues);
			return venues.length;
		}

		@Override
		public String getStatus(String no) throws RemoteException {
			for (Iterator iterator = devices.iterator(); iterator.hasNext();) {
				DeviceInfo device = (DeviceInfo) iterator.next();
				if (device.getDeviceID().equalsIgnoreCase(no)) {
					return "In Vincinity";
				}
			}
			return null;
		}

	};

	@Override
	public IBinder onBind(Intent intent) {
		return m_binder;
	}

	@Override
	public void onStart(Intent intent, int startId) {
		super.onStart(intent, startId);
		dbHelper = new ClientDBAdapter(this);
//		dbHelper.kill();
		dbHelper.open();
		Toast.makeText(this, R.string.service_start, Toast.LENGTH_SHORT).show();
		//myDeviceInfo = new DeviceInfo(bssid,"Linus Harling", "KTHOPEN-WPA", "0706863328", ipAddress, localport);
		myDeviceInfo = new DeviceInfo("0706863328", "Linus Harling");
		myDeviceInfo.setBssid(bssid);
		myDeviceInfo.setIpAddress(ipAddress);
		myDeviceInfo.setSsid("KTHOPEN-WPA");
		myDeviceInfo.setPort(localport);
		connect();
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		ping = listening = false;
		server = null; 
		client = null;
		dbHelper.close();
		Toast.makeText(this, R.string.service_destroy, Toast.LENGTH_SHORT).show();
	}

	public void connect() {
		try {
			server = new ServerThread(localport);
			client = new CheckInThread();
			ping = listening = true;
			server.start();
			client.start();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private void receiveObject(DeviceList dl) {
		devices = dl;
		for (Iterator iterator = dl.iterator(); iterator.hasNext();) {
			DeviceInfo device = (DeviceInfo) iterator.next();
			
		}
		//Toast.makeText(getApplicationContext(), R.string.service_got_devices, Toast.LENGTH_SHORT).show();		
	}
	private void receiveObject(VenueList vl) {
		venuelist = vl;
		dbHelper.addVenueActivities(vl);
		//Toast.makeText(getApplicationContext(), R.string.service_got_venues, Toast.LENGTH_SHORT).show();		
	}

	class ServerThread extends ServerSocket implements Runnable {
		int port;
		Socket receiver = new Socket();
		ObjectInputStream ois;
		private Thread t = new Thread(this);

		public ServerThread(int port) throws IOException {
			super(port);
			//this.port = port;
		}	

		public void start() {
			// TODO Auto-generated method stub
			t.start();
		}

		@Override
		public void run() {
			Object tmp = null;
			while (listening) {
				try {
					receiver = this.accept();
					ois = new ObjectInputStream(receiver.getInputStream());
					tmp = ois.readObject();
					if (tmp instanceof DeviceList) {
						receiveObject((DeviceList)tmp);
					} else if (tmp instanceof VenueList) {
						receiveObject((VenueList)tmp);
					} else {
						//fuckup
					}
				} catch (IOException e) {
					e.printStackTrace();
				} catch (ClassNotFoundException e) {
					e.printStackTrace();
				}
			}
		}
	}

	class CheckInThread implements Runnable {
		//String address;
		//int port;
		Socket socket;
		ObjectOutputStream oos;
		private Thread t = new Thread(this);
		private int counter = 0;
		//DeviceInfo device;

		public CheckInThread() {

		}

		public void start() {
			// TODO Auto-generated method stub
			t.start();
		}

		@Override
		public void run() {
			while (ping) {
				try {
					servicestatus += "P: "+Integer.toString(counter)+" "+remoteAddress+" "+Integer.toString(remoteport);
					socket = new Socket(remoteAddress, remoteport);
					oos  = new ObjectOutputStream(socket.getOutputStream());
					oos.writeObject(myDeviceInfo);
					oos.flush();
					//oos.close();
					//socket.close();
					counter++;
					Thread.sleep(CHECK_IN_INTERVAL);
				} catch (InterruptedException ie) {
					ie.printStackTrace();					
				} catch (IOException e) {
					e.printStackTrace();
				}

			}
		}
	}
}